#include "CANBus.h"
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <linux/can/error.h>  // CAN 错误定义头文件
#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cstring>
#include <iostream>
#include <errno.h>  // 用于 strerror
#include <fcntl.h>  // 新增：包含 O_NONBLOCK 和 fcntl 的定义

namespace jetcar {

static int can_sock = -1;  // 全局 CAN socket 文件描述符

// 修复 initCAN 函数：变量错误+完整初始化流程
bool initCAN(const std::string &ifname) {
    // 先尝试关闭接口（避免已占用）
    std::string cmd = "ip link set " + ifname + " down";
    system(cmd.c_str());  // 忽略返回值，即使关闭失败也继续

    // 1. 关闭已存在的 CAN socket（避免重复初始化）
    if (can_sock >= 0) {
        close(can_sock);
        can_sock = -1;
    }

    // 2. 创建 CAN socket
    can_sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (can_sock < 0) {
        std::cerr << "[CAN] socket create failed: " << strerror(errno) << std::endl;
        return false;
    }

    // 3. 绑定 CAN 接口（ifname 是 "can0"）
    struct ifreq ifr;
    std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0';  // 确保字符串终止
    if (ioctl(can_sock, SIOCGIFINDEX, &ifr) < 0) {
        std::cerr << "[CAN] ioctl failed for " << ifname << ": " << strerror(errno) << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }

    struct sockaddr_can addr;
    std::memset(&addr, 0, sizeof(addr));
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    if (bind(can_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        std::cerr << "[CAN] bind failed: " << strerror(errno) << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }

    // 4. 配置 CAN 波特率（关键：用 ifname 而非未定义的 can_device）
    cmd = "ip link set " + ifname + " type can bitrate 500000";
    if (system(cmd.c_str()) != 0) {
        std::cerr << "[CAN] set bitrate failed for " << ifname << ": " << strerror(errno) << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }
    std::cout << "[CAN] set bitrate success"<<std::endl;

    // 5. 启动 CAN 接口（用 ifname）
    cmd = "ip link set " + ifname + " up";
    if (system(cmd.c_str()) != 0) {
        std::cerr << "[CAN] set " << ifname << " up failed: " << strerror(errno) << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }
    std::cout << "[CAN] set " << ifname << " up success"<<std::endl;

    // 6. 验证接口状态（确保是 UP 状态）
    struct ifreq ifr_state;
    std::strncpy(ifr_state.ifr_name, ifname.c_str(), IFNAMSIZ - 1);
    ifr_state.ifr_name[IFNAMSIZ - 1] = '\0';
    if (ioctl(can_sock, SIOCGIFFLAGS, &ifr_state) < 0) {
        std::cerr << "[CAN] check " << ifname << " state failed: " << strerror(errno) << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }
    if (!(ifr_state.ifr_flags & IFF_UP)) {
        std::cerr << "[CAN] " << ifname << " state is DOWN after init" << std::endl;
        close(can_sock);
        can_sock = -1;
        return false;
    }

    std::cout << "[CAN] initialized successfully on " << ifname << " (bitrate 500k)" << std::endl;
    return true;
}

void closeCAN() {
    if (can_sock >= 0) {
        // 关闭接口（可选，优雅释放）
        std::string ifname = "can0";  // 可改为从配置读取，这里简化
        std::string cmd = "ip link set " + ifname + " down";
        system(cmd.c_str());
        
        close(can_sock);
        can_sock = -1;
        std::cout << "[CAN] closed successfully" << std::endl;
    }
}

#include <string>  // 需包含 string 头文件

bool sendCANFrame(uint32_t id, const uint8_t *data, uint8_t len, std::string& error_msg) {
    // 初始化错误信息（清空，避免残留之前的错误）
    error_msg.clear();

    // 1. 基础校验：socket 无效
    if (can_sock < 0) {
        error_msg = "[CAN] 发送失败：CAN 接口未初始化（can_sock=" + std::to_string(can_sock) + "）";
        return false;
    }

    // 2. 检测 CAN 接口状态（核心：判断接口是否真的 UP）
    struct ifreq ifr;
    std::strncpy(ifr.ifr_name, "can0", IFNAMSIZ - 1);
    ifr.ifr_name[IFNAMSIZ - 1] = '\0';
    if (ioctl(can_sock, SIOCGIFFLAGS, &ifr) < 0) {
        error_msg = "[CAN] 发送失败：获取接口状态失败，错误原因：" + std::string(strerror(errno));
        return false;
    }
    if (!(ifr.ifr_flags & IFF_UP)) {
        error_msg = "[CAN] 发送失败：CAN0 接口处于 DOWN 状态，无法发送数据";
        return false;
    }

    // 3. 校验数据长度（CAN 帧最大 8 字节）
    if (len > 8) {
        error_msg = "[CAN] 发送失败：数据长度超过 8 字节（实际长度=" + std::to_string(len) + "），已自动截断为 8 字节";
        len = 8;  // 截断超长数据，仍尝试发送（可选，也可直接返回失败）
    }

    // 4. 构造 CAN 帧
    struct can_frame frame;
    std::memset(&frame, 0, sizeof(frame));
    frame.can_id = id;
    frame.can_dlc = len;
    if (len > 0 && data != nullptr) {
        std::memcpy(frame.data, data, len);
    } else if (len > 0 && data == nullptr) {
        error_msg = "[CAN] 发送失败：数据长度 > 0，但数据指针为 NULL";
        return false;
    }

    // 5. 发送数据
    int res = write(can_sock, &frame, sizeof(frame));
    if (res != (int)sizeof(frame)) {
        error_msg = "[CAN] 发送失败：write 系统调用返回异常，返回值=" + std::to_string(res) + 
                    "（期望返回=" + std::to_string(sizeof(frame)) + "），错误原因：" + std::string(strerror(errno));
        return false;
    }

    // 6. 解析总线错误帧（检测物理层错误）
    struct can_frame err_frame;
    // 设置非阻塞读取（避免无错误时阻塞）
    int flags = fcntl(can_sock, F_GETFL, 0);
    fcntl(can_sock, F_SETFL, flags | O_NONBLOCK);
    
    res = read(can_sock, &err_frame, sizeof(err_frame));
    // 恢复阻塞模式（不影响后续发送）
    fcntl(can_sock, F_SETFL, flags);

    if (res > 0 && (err_frame.can_id & CAN_ERR_FLAG)) {
        // 存在总线错误，解析错误类型
        error_msg = "[CAN] 发送失败：总线物理层错误（错误码=0x" + 
                    std::to_string(err_frame.can_id & CAN_ERR_MASK) + "），具体原因：";
        if (err_frame.can_id & CAN_ERR_TX_TIMEOUT) {
            error_msg += "发送超时（总线无响应，可能是接线松动/驱动未供电）";
        } else if (err_frame.can_id & CAN_ERR_BUSOFF) {
            error_msg += "总线关闭（硬件故障，需重启接口）";
        } else if (err_frame.can_id & CAN_ERR_ACK) {
            error_msg += "无应答（电机驱动未收到，可能是 ID/波特率不匹配）";
        } else {
            error_msg += "未知总线错误";
        }
        return false;
    } else if (res < 0 && errno != EAGAIN) {
        // 读取错误帧时发生其他错误（非“无数据可读”）
        error_msg = "[CAN] 发送警告：读取总线错误帧失败，错误原因：" + std::string(strerror(errno));
        // 此处不返回 false，仅警告（不影响正常发送）
    }

    // 7. 发送成功：拼接成功日志（可选，也可清空）
    #if 0
        std::string success_msg = "[CAN] 发送成功：ID=0x" + std::to_string(id) + 
                                "，长度=" + std::to_string(len) + "，数据：";
        for (int i = 0; i < len; i++) {
            success_msg += std::to_string((int)frame.data[i]) + " ";
        }
        error_msg = success_msg;  // 成功时也将信息写入（可选，若仅需错误信息则清空）
    #endif
    return true;
}

} // namespace jetcar


#if  0

#include "CANBus.h"
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <unistd.h>
#include <cstring>
#include <iostream>


namespace jetcar {

static int can_sock = -1;

bool initCAN(const std::string &ifname) {
    can_sock = socket(PF_CAN, SOCK_RAW, CAN_RAW);
    if (can_sock < 0) {
        std::cerr << "[CAN] socket create failed\n";
        return false;
    }
    struct ifreq ifr;
    std::strncpy(ifr.ifr_name, ifname.c_str(), IFNAMSIZ-1);
    ifr.ifr_name[IFNAMSIZ-1] = '\0';
    if (ioctl(can_sock, SIOCGIFINDEX, &ifr) < 0) {
        std::cerr << "[CAN] ioctl failed for " << ifname << std::endl;
        close(can_sock); can_sock = -1; return false;
    }
    struct sockaddr_can addr;
    std::memset(&addr, 0, sizeof(addr));
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
    if (bind(can_sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        std::cerr << "[CAN] bind failed\n";
        close(can_sock); can_sock = -1; 
        return false;
    }
    std::cout << "[CAN] initialized on " << ifname << std::endl;
    
    // 3. 配置 CAN 波特率（关键！必须与电机驱动一致，如 500k）
    // 方式 1：通过系统命令配置（简单，需 root 权限）
    std::string cmd = "ip link set " + can_device + " type can bitrate 500000";
    if (system(cmd.c_str()) != 0) {
        perror("set can bitrate failed");
        close(sockfd);
        return false;
    }

    // 4. 启动 CAN 接口
    cmd = "ip link set " + can_device + " up";
    if (system(cmd.c_str()) != 0) {
        perror("set can up failed");
        close(sockfd);
        return false;
    }

    // 5. 保存 socket 文件描述符（用于后续发送/接收）
    can_sockfd = sockfd;
    std::cout << "[CAN] 接口 " << can_device << " 初始化成功（波特率 500k）" << std::endl;
    return true;
}

void closeCAN() {
    if (can_sock >= 0) { close(can_sock); can_sock = -1; }
}

bool sendCANFrame(uint32_t id, const uint8_t *data, uint8_t len) {
    if (can_sock < 0) return false;
    struct can_frame frame;
    std::memset(&frame, 0, sizeof(frame));
    frame.can_id = id;
    frame.can_dlc = len > 8 ? 8 : len;
    if (len > 0 && data) std::memcpy(frame.data, data, frame.can_dlc);
    int res = write(can_sock, &frame, sizeof(frame));
    return res == (int)sizeof(frame);
}

} // namespace jetcar

#endif